﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Linq.Expressions;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Linq;

namespace MongoDB.Common
{
    public class MongoDBbase:IMongoDBbase
    {
        protected String _connectionString;
        protected String _databaseName;
        protected MongoServer _server;
        protected MongoDatabase _database;

        #region 初始化操作
        /// <summary>
        /// 初始化操作
        /// </summary>
        public MongoDBbase()
        {
            _connectionString = ConfigurationManager.AppSettings["MongoDBConnection"];// "mongodb://127.0.0.1:27017/?safe=true";
            _databaseName = "UsersDB";// ConfigurationManager.AppSettings["MongoDB"];
            _server = MongoServer.Create(_connectionString);
            _database = _server.GetDatabase(_databaseName);
        }
        public MongoDBbase(String Connection,String DatabaseName)
        {
            _server = MongoServer.Create(Connection);
            _database = _server.GetDatabase(DatabaseName);
        }
        #endregion

        #region 插入操作
        /// <summary>
        /// 插入操作
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        /// <param name="t"></param>
        public virtual void Insert<T>(T t)
        {
            try
            {
                var collection = _database.GetCollection<T>(t.GetType().Name);
                SafeModeResult smRes = collection.Insert(t, SafeMode.True);
                if (!smRes.Ok)
                {
                    throw new MongoSafeModeException(smRes.LastErrorMessage, smRes);
                }

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        #endregion

        #region 批量插入
        public virtual void InsertBatch<T>(IList<T> list)
        {
            try
            {
                if (list.Count == 0) return;
                var collection = _database.GetCollection<T>(list.FirstOrDefault().GetType().Name);
                IEnumerable<SafeModeResult> smRes = collection.InsertBatch(list, SafeMode.True);
                foreach (var s in smRes)
                {
                    if (!s.Ok)
                    {
                        throw new MongoSafeModeException(s.LastErrorMessage, s);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        #endregion

        #region 更新操作
        /// <summary>
        /// 更新操作
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public virtual void Update<T>(T t, ObjectId id)
        {
            try
            {

                var collection = _database.GetCollection<T>(t.GetType().Name);
                //var query = Query.EQ("_id", id);
                var query = new QueryDocument { { "_id", id } };
                var update = new UpdateDocument { t.ToBsonDocument() };
                SafeModeResult smRes = collection.Update(query, update, SafeMode.True);
                if (!smRes.Ok)
                {
                    throw new MongoSafeModeException(smRes.LastErrorMessage, smRes);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        /// <summary>
        /// 更新操作,需要_id属性，才能更新，否则为插入
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public virtual void Save<T>(T t)
        {
            try
            {
                var collection = _database.GetCollection<T>(t.GetType().Name);
                //var query = Query.EQ("_id", id);
                SafeModeResult smRes = collection.Save(t, SafeMode.True);
                if (!smRes.Ok)
                {
                    throw new MongoSafeModeException(smRes.LastErrorMessage, smRes);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        /// <summary>
        /// 更新操作，更新多个文档
        /// </summary>
        /// <param name="t"></param>
        /// <param name="IDict"></param>
        public virtual void UpdateMulti<T>(T t, IDictionary<string, object> IDict)
        {
            try
            {
                var collection = _database.GetCollection<T>(t.GetType().Name);
                var query = new QueryDocument(IDict);
                var update = new UpdateDocument { t.ToBsonDocument() };
                collection.Update(query, update, UpdateFlags.Multi);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 更新操作
        /// </summary>
        /// <param name="t"></param>
        /// <param name="IDict">字典</param>
        public virtual void Update<T>(T t, IDictionary<string, object> IDict)
        {
            try
            {
                var collection = _database.GetCollection<T>(t.GetType().Name);
                //var query = Query.EQ("_id", id);
                var query = new QueryDocument(IDict);
                var update = new UpdateDocument { t.ToBsonDocument() };
                collection.Update(query, update);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 更新或者插入
        /// </summary>
        /// <param name="t"></param>
        /// <param name="iDict"></param>
        public virtual void Upsert<T>(T t, IDictionary<string, object> iDict)
        {
            try
            {
                var collection = _database.GetCollection<T>(t.GetType().Name);
                var query = new QueryDocument(iDict);
                var update = new UpdateDocument { t.ToBsonDocument() };
                collection.Update(query, update, UpdateFlags.Upsert);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }


        #endregion

        #region 读取单条记录
        /// <summary>
        ///读取单条记录
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public virtual T Single<T>(Expression<Func<T, bool>> func)
        {
            try
            {
                var collection = _database.GetCollection<T>(typeof(T).Name);
                return collection.AsQueryable<T>().Where(func).FirstOrDefault();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        #endregion

        #region 获取集合
        /// <summary>
        ///获取集合
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public virtual IList<T> List<T>()
        {
            try
            {
                var collection = _database.GetCollection<T>(typeof(T).Name);
                return collection.AsQueryable<T>().ToList();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }


        /// <summary>
        ///获取集合
        /// </summary>
        /// <param name="func">条件委托函数</param>
        /// <returns></returns>
        public virtual IList<T> List<T>(Expression<Func<T, bool>> func)
        {
            try
            {
                var collection = _database.GetCollection<T>(typeof(T).Name);
                return collection.AsQueryable<T>().Where(func).ToList();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="func"></param>
        /// <param name="pageCount"></param>
        /// <returns></returns>
        public virtual IList<T> List<T>(int pageIndex, int pageSize, out int pageCount, Expression<Func<T, bool>> func)
        {

            try
            {
                var collection = _database.GetCollection<T>(typeof(T).Name).AsQueryable<T>().Where(func);
                pageCount = Convert.ToInt32(collection.Count());
                var pagelist = collection.Skip(pageSize * (pageIndex - 1))
                                                  .Take(pageSize).Select(i => i).ToList();
                return pagelist;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        #endregion

        #region 执行JS脚本
        /// <summary>
        /// 执行Javascript脚本
        /// </summary>
        /// <param name="javascriptcode"></param>
        public virtual BsonValue ExecuteJavaScript(string javascriptcode, params object[] args)
        {
            try
            {
                return _database.Eval(new BsonJavaScript(javascriptcode), args);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        #endregion
    }
}
